# =================================================================     使用 对象 组织数据
# 设计一个类（制作表）
class Student:
    name = None
    gender = None
    nationality = None
    native_place = None
    age = None
# 创建一个对象（打印表）
stu1 = Student()
# 对象属性进行赋值（填写表）
stu1.name = "张三"
stu1.gender = "男"
stu1.nationality = "中国"
stu1.native_place = "云南"
stu1.age = 23

# 获取对象中的信息
print(stu1.name)
print(stu1.gender)
print(stu1.nationality)
print(stu1.native_place)
print(stu1.age)
# ==========================================================================       类、 成员方法、 self关键字
class Student:                               # --- student-类名称  name-成员变量  say_hi-成员方法  msg-参数列表
    name = None
    def say_hi1(self):
        print(f"大家好，我是{self.name}")

    def say_hi2(self, msg):
        print(f"你好，我是{self.name}, {msg}")
stu = Student()
stu.name ="zhangsan"
stu.say_hi1()
stu.say_hi2("我学习好")
# ====================================================================================== 类和对象
                                                   # --- 类是设计图纸，对象是基于图纸生产的具体实体
                                                   # --- 面向对象编程：设计类，基于类创建对象，并使用对象来完成具体的工作
class Clock:
    id = None
    price = None
    def ring(self):
        import winsound
        winsound.Beep(2000, 3000)
clock1 = Clock()
clock1.id ="12345"
clock1.price = 12
print(f"闹钟1的id是：{clock1.id}，价格是：{clock1.price}")
clock1.ring()

clock2 = Clock()
clock2.id = "67890"
clock2.price = 21
print(f"闹钟2的id是：{clock2.id}，价格是：{clock2.price}")
clock2.ring()
# ====================================================================================== 构造方法   __init__()
class Student:
    name = None             # 这里可以忽略不写（写：self.name 赋值；不写：self.name 声明且赋值）
    age = None
    tel = None
    def __init__(self, name, age, tel):
        self.name = name
        self.age = age
        self.tel = tel
    print("student创建了一个对象")
stu = Student("zhangsan", 14, 1222222222)
print(stu.name)
print(stu.age)
print(stu.tel)
# ------------------------------------------------------  案例：   输入10名学生的信息
class Student:
    def __init__(self, name, age, adre):
        self.name = name
        self.age = age
        self.adre = adre

i = 1
for i in range(1, 11):
    print(f"当前录入第{i}位学生信息，总共需录入10位学生信息")
    name = input(f"请输入学生姓名：")
    age = input(f"请输入学生年龄：")
    adre = input(f"请输入学生地址：")
    stu = Student(name, age, adre)
    print(f"学生{i}信息录入完成，信息为：【学生姓名：{stu.name}，年龄：{stu.age}，地址：{stu.adre}】")

# ====================================================================================== 魔术方法
# 魔术方法：
#    __init__  构造方法
#    __str__   字符串方法
#    __lt__    小于、大于符号比较
#    __le__    小于等于、大于等于符号比较
#    __eq__    == 符号比较
# ---------------------------------------------------------   __str__() 字符串
class Student:
    def __init__(self, name, age):
        self.name =name
        self.age =age

    def __str__(self):
        return f"输出的姓名是：{self.name},年龄是：{self.age}"
stu = Student("zhangsan", 14)
print(stu)   # 直接返回字符串
print(str(stu))  # 转变成字符串再输出
# ---------------------------------------------------------   __lt__() <、  >
class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def __lt__(self, other):
         return self.age < other.age
stu1 = Student("zhangsan", 13)
stu2 = Student("lisi", 21)
print(stu1 < stu2)  # ---不用魔术方法，就只是比较内存地址是否相同，即使完全相同的内容，内存地址也不一样，所以始终会报错
print(stu1 > stu2)
# ---------------------------------------------------------   __le__()<=、  >=
class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def __le__(self, other):
        return self.age <= other.age
stu1 = Student("zhangsan", 17)
stu2 = Student("lisi", 20)
print(stu1 <= stu2)
print(stu1 >= stu2)
# ---------------------------------------------------------   __eq__() ==
class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def __eq__(self, other):
        return self.age == other.age
stu1 =Student("zhangsan", 21)
stu2 = Student("lisi", 21)
print(stu1 == stu2)  # ---不用魔术方法，就只是比较内存地址是否相同，即使完全相同的内容，内存地址也不一样，所以始终是False
# ====================================================================================== 封装
# 面向对象编程是许多编程语言都支持的编程思想（基于模板-类去创建实体-对象，使用对象完成功能开发）
# 面向对象的三大主要特性：封装、继承、多态
# 封装：将现实事物中的属性、行为，封装到类中（成员变量、成员方法），从而实现程序对现实事物的描述
# ------------------------------------------------------------------------------ 私有成员
class Phone:
    __current_voltage = 1
    def __keep_single_core(self):
        print("让CPU以单核模式运行")
    def call_by_5g(self):
        if self.__current_voltage == 1:   # 私有成员和方法不能直接使用，但可以被内部的其他成员使用，即出了call_by_5g,就无法正常使用
            print("5g通话已开启")
        else:
            self.__keep_single_core()
            print("电量不足，无法使用5g通话，已设置为单核运行进行省电")

phone = Phone()
# phone.__keep_single_core()
# print(phone.__current_voltage)
phone.call_by_5g()
# ---------------------------------------------------------------  案例：设计带有私有成员的手机
class Phone:
    __is_5g_enable = "False"
    def _check_5g(self):
        if self.__is_5g_enable == "Ture":
            print("5g开启")
        else:
            print("5g关闭，使用4g网络")
    def call_by_5g(self):
        self._check_5g()
        print("正在通话中")
phone = Phone()
phone.call_by_5g()
# ====================================================================================== 继承
# --------  单继承
class Phone:
    IMEI = None     # --序列
    producer = "HM"  # --厂商
    def call_by_4g(self):
        print("4g运行中")

class Phone2022(Phone): # --- Phone2022为子类，Phone为父类
    face_id = "10001"
    def call_by_5g(self):
        print("5g运行中")

phone2022 =Phone2022()
print(phone2022.producer)
phone2022.call_by_4g()
phone2022.call_by_5g()
# --------  多继承
class Phone:
    IMEI =None     # --序列
    producer = "phone"  # --厂商
    def call_by_4g(self):
        print("4g运行中")
class NFCReader:
    nfc_type = "第五代"
    producer = "NFC"
    def read_card(self):
        print("NFC读卡")
    def write_card(self):
        print("NFC写卡")
class RemoteControl:
    rc_type = "红外遥控"
    def control(self):
        print("红外遥控开启了")

class MyPhone(Phone, NFCReader, RemoteControl):
    pass                                        # --- pass 关键字，没有内容，只是补全语法的功能

myphone = MyPhone()
print(myphone.rc_type)
myphone.control()
myphone.read_card()
myphone.write_card()
myphone.call_by_4g()
print(myphone.producer)   # --- phone、NFCReader都有producer，谁在左边打印谁的

# ====================================================================================== 复写父类成员和调用父类成员
# 调用父类： 父类名成员变量           super().成员变量
#          父类名.成员方法(self)    super().成员方法()

class Phone:
    IMEI = None     # --序列
    producer = "HM"  # --厂商
    def call_by_4g(self):
        print("4g运行中")
# ----- 定义子类，复写父类的成员属性和成员方法
class MyPhone(Phone):
    producer = "ITHM"
    def call_by_4g(self):
        print("开启CPU单核模式，确保通话时省电")
        # 方法1 --调取父类原来的内容
        # print(f"父类的厂商是：{Phone.producer}")
        # Phone.call_by_4g(self)
        # 方法2
        print(f"父类的厂商是：{super().producer}")
        super().call_by_4g()
        print("关闭CPU单核模式，确保性能")
phone = MyPhone()
phone.call_by_4g()
print(phone.producer)

# ====================================================================================== 变量的类型注解
# 基础数据类型注解
var_1: int = 10
var_2: bool = True

# 类对象类型注解
class Student:
    pass
stu : Student = Student()

# 基础容器类型注解
my_list: list = [1, 2, 3]
my_dict: dict = {"itheima": 666}

# 容器类型详细注解
my_list1: list[int] = [1, 2, 3]
my_tuple: tuple[int, str, bool] = (1, "itheima", True)

# 在注释中进行类型注解
import random
import json
var = random.randint(1, 10)   # type: int     # type后紧跟：
var2 = json.loads('{"name","zhangsan"}')   # type: dict[str, str]

def func():
    return 10
var3 = func()  # type: int
# 类型注解的限制(类型注解只是提示作用，即使无法一一对应，也不会报错）

# ====================================================================================== 函数的方法类型注解
# 对形参进行类型注解
def add(x:int, y:int):
    return x + y
add()

# 对返回值进行类型注解
def func(data: list) -> list:
    return data

# ====================================================================================== Union联合类型注解
from typing import Union

my_list: list[Union[int, str]] = [1, 2, "itheima", "itcast"]
my_dict: dict[[str, Union[int, str]]] = {"name": "zhangsan", "age": 11}
def func1(data: Union[int,str]) -> Union[int,str]:
    pass
func1()
# ====================================================================================== 多态
# 多态：多种状态，完成某个行为时，使用不同的对象会得到不同的状态
# 多态常作用在继承关系上：如函数形参接收父类，实际子类工作，用以获得同意行为的不同状态
class Animal:          # --- 抽象类（接口）： 包含抽象方法的类（Animal）
    def speak(self):   # --- 抽象方法：方法体是空实现（pass）的方法
        pass
class Dog(Animal):
    def speak(self):
        print("汪汪汪")
class Cat(Animal):
    def speak(self):
        print("喵喵喵")

def make_noise(animal:Animal):
    animal.speak()

dog = Dog()
cat = Cat()
make_noise(dog)
make_noise(cat)
# ------------------------------------------------- 案例：空调的制冷制热摆风标准
# ------- 标准设计（即：顶层设计）
class AC:
    def make_cool(self):
        pass
    def make_hot(self):
        pass
    def swing_l_r(self):
        pass
# ------- 由具体的类实现
class MD_AC(AC):
    def make_cool(self):
        print("美的制冷")
    def make_hot(self):
        print("美的制热")
    def swing_l_r(self):
        print("美的摆风")

class GL_AC(AC):
    def make_cool(self):
        print("格力制冷")
    def make_hot(self):
        print("格力制热")
    def swing_l_r(self):
        print("格力摆风")
# ------- 同一种行为
def cool(ac:AC):
    ac.make_cool()
def hot(ac:AC):
    ac.make_hot()
def swing(ac:AC):
    ac.swing_l_r()

md = MD_AC()
gl = GL_AC()
# ------- 不同的运行状态
cool(md)
hot(md)
swing(md)

cool(gl)
hot(gl)
swing(gl)

# ==============================================================  对比美的和读取文件的类
class AC:
    def make_cool(self):
        pass

class MD(AC):
    def make_cool(self):
        print("美的制冷")

def cool(ac):
    ac.make_cool()

md = MD()
cool(md)
# ----------------------------------------------------
class File:
    def read_data(self):
        pass

class TextFile(File):
    def __init__(self, path):
        self.path = path

    def read_data(self):
        f = open(self.path, 'r', encoding="UTF-8")
        lines = f.readlines()

text = TextFile("E:/数据.txt")
t = text.read_data()




